package com.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dao.ArticleDAO;
import com.dao.QuestionActionDAO;
import com.dao.QuestionDAO;
import com.dao.RelationDAO;
import com.dao.TagDAO;
import com.dao.TimelineDAO;
import com.dao.UserDAO;
import com.model.Tag;
import com.model.Timeline;
import com.model.User;
import com.service.ArticleService;
import com.service.QuestionService;
import com.service.UserService;
import com.util.Page;
import com.util.TimeEvent;

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDAO userDAO;

	@Autowired
	private TagDAO tagDAO;

	@Autowired
	private RelationDAO relationDAO;

	@Autowired
	private TimelineDAO timelineDAO;

	@Autowired
	private ArticleDAO articleDAO;

	@Autowired
	private QuestionDAO questionDAO;

	@Autowired
	private QuestionService questionService;

	@Autowired
	private ArticleService articleService;
	
	@Autowired
	private QuestionActionDAO questionActionDAO;

	@Transactional
	public User login(String nameOrEmail, String password) {
		List<User> list = userDAO.findByNameOrEmail(nameOrEmail);
		if (list.size() > 0) {
			User u = list.get(0);
			if (password.equals(u.getPassword())) {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				// Date date = sdf.parse(birthday);
				Date date = u.getLastLoginTime();
				String dateStr = sdf.format(date);
				Date today = new Date();
				String todayStr = sdf.format(today);
				Date date_without_time = null;
				Date today_without_time = null;
				try {
					date_without_time = sdf.parse(dateStr);
					today_without_time = sdf.parse(todayStr);
				} catch (ParseException e) {
					e.printStackTrace();
				}

				if (date_without_time.getTime() == today_without_time.getTime()) {
					u.setLastLoginTime(today);
				} else if (today.getTime() - date.getTime() < 24 * 60 * 60) {
					u.setLastLoginTime(today);
					u.setSequenceLogin(u.getSequenceLogin() + 1);
				} else {
					u.setLastLoginTime(today);
					u.setSequenceLogin(0);
				}
				if (u.getSequenceLogin() >= 5) {
					u.setVip(1);
				} else {
					u.setVip(0);
				}
				userDAO.update(u);

				return u;
			}
		}
		return null;
	}

	@Transactional
	public boolean registerUser(User user) {
		user.setAnswersNum(0);
		user.setFavorNum(0);
		user.setFansNum(0);
		user.setFollowNum(0);
		user.setArticleNum(0);
		user.setScore(200);
		user.setQuestionsNum(0);
		user.setCreateAt(new Date());
		user.setLastLoginTime(new Date());
		user.setSequenceLogin(1);
		user.setVip(0);
		user.setGender(2);
		boolean flag = userDAO.addUser(user);
//		user.setPrivateUrl("home/"+user.getId());
//		userDAO.update(user);
		return flag;
	}

	@Transactional
	public Tag addUserTag(String tagName, int userId) {
		List<Tag> tagList = tagDAO.findByName(tagName);
		int tagId = 0;
		if (tagList.size() == 0) {
			Tag tag = new Tag();
			tag.setName(tagName);
			tag.setDescription(tagName);
			tag.setArticleNum(0);
			tag.setQuestionNum(0);
			tag.setUserNum(1);
			tag.setIsElite(0);
			tag.setImage("");
			tagDAO.addTag(tag);
			tagId = tag.getId();
			userDAO.addUserTag(tagId, userId);
			return tag;
		} else {
			Tag tag = tagList.get(0);
			tagId = tag.getId();
			if (userDAO.isTagExist(tagId, userId)) {
				return tag;
			} else {
				tag.setUserNum(tag.getUserNum() + 1);
				tagDAO.update(tag);
				userDAO.addUserTag(tagId, userId);
				return tag;
			}

		}
	}

	@Transactional
	public void removeUserTag(int tagId, int userId) {
		Tag tag = tagDAO.findById(tagId);
		tag.setUserNum(tag.getUserNum() - 1);
		tagDAO.update(tag);
		userDAO.deleteUserTag(tagId, userId);
	}

	@Transactional
	public boolean isNameExist(String name) {
		// TODO Auto-generated method stub
		return userDAO.isNameExist(name);
	}
	
	
	@Transactional
	public User findByPriUrl(String uri) {
		// TODO Auto-generated method stub
		return userDAO.findByPriUrl(uri);
	}

	@Transactional
	public boolean isPrivateUrlExist(String privateUrl,int excludeId) {
		// TODO Auto-generated method stub
		return userDAO.isPrivateUrlExist(privateUrl,excludeId);
	}

	@Transactional
	public boolean isEmailExist(String email) {
		// TODO Auto-generated method stub
		return userDAO.isEmailExist(email);
	}

	@Transactional
	public void updateUser(User user) {
		userDAO.update(user);

	}

	@Transactional
	public User getUserById(int id) {
		return userDAO.findById(id);
	}

	@Transactional
	public String addAttention(int userId, int userById) {
		String result = relationDAO.addAttention(userId, userById);
		if ("success".equals(result)) {
			userDAO.addFansNum(userById);
			userDAO.addFollowNum(userId);
		}
		return result;
	}

	@Transactional
	public String removeAttention(int userId, int userById) {
		String result = relationDAO.removeAttention(userId, userById);
		if ("success".equals(result)) {
			userDAO.reduceFollowNum(userId);
			userDAO.reduceFansNum(userById);
		}
		return result;
	}

	@Transactional
	public List<Tag> getUserTags(int userId) {
		return userDAO.getUserTags(userId);
	}

	@Transactional
	public List<TimeEvent> getUserTimeline(int userId, long lasttime,
			int pageSize) throws ParseException {
		String ids = relationDAO.findUserAttentionAsString(userId);
		if (ids.length() != 0) {
			ids += "," + userId;
		} else {
			ids += userId;
		}
		List<Timeline> events = timelineDAO.getEventPageByUserId(ids, lasttime,
				pageSize);
		StringBuffer articleIds = new StringBuffer();
		StringBuffer questionIds = new StringBuffer();
		StringBuffer answerIds = new StringBuffer();
		for (Timeline event : events) {
			if ("article".equals(event.getAction())) {
				if (articleIds.length() != 0) {
					articleIds.append(",");
				}
				articleIds.append(event.getTargetId());
			}

			if ("question".equals(event.getAction())) {
				if (questionIds.length() != 0) {
					questionIds.append(",");
				}
				questionIds.append(event.getTargetId());
			}

			if ("answer".equals(event.getAction())) {
				if (answerIds.length() != 0) {
					answerIds.append(",");
				}
				answerIds.append(event.getTargetId());
			}
		}

		List<HashMap> articles = articleDAO.findByIds(articleIds.toString());
		List<HashMap> questions = questionDAO.findByIds(questionIds.toString());
		List<HashMap> answers = questionDAO.findByIds(answerIds.toString());
		List<TimeEvent> result = new ArrayList<TimeEvent>();

		
		for(int ar = 0; ar<articles.size(); ar++){
			Map article = articles.get(ar);
			TimeEvent timeEvent = new TimeEvent();
			timeEvent.setEventName("article");
			timeEvent.setMap(article);
			timeEvent.setEventTime((Date) article.get("create_at"));
			result.add(timeEvent);
		}
		
		for(int qu=0; qu<questions.size(); qu++){
			Map question = questions.get(qu);
			TimeEvent timeEvent = new TimeEvent();
			timeEvent.setEventName("question");
			timeEvent.setMap(question);
			timeEvent.setEventTime((Date) question.get("question_at"));
			result.add(timeEvent);
		}
		
		for(int an=0; an<answers.size(); an++){
			Map answer = answers.get(an);
			TimeEvent timeEvent = new TimeEvent();
			timeEvent.setEventName("answer");
			timeEvent.setMap(answer);
			timeEvent.setEventTime((Date) answer.get("answer_at"));
			result.add(timeEvent);
		}
		Collections.sort(result, new Comparator() {
		      public int compare(Object o1, Object o2) {
		    	  TimeEvent t1 = (TimeEvent)o1;
		    	  TimeEvent t2 = (TimeEvent)o2;
		    	  return t2.getEventTime().compareTo(t1.getEventTime());
		      }
		 });

		return result;
	}

	@Transactional
	public Page getUserCollect(int userId, int page, int pageSize) {
		Page pageobj = timelineDAO.findCollectEventPageByUserId(
				userId, page, pageSize);
		
		List<Timeline> events = pageobj.getList();
		
		StringBuffer articleIds = new StringBuffer();
		StringBuffer questionIds = new StringBuffer();
		Map<String, Date> map = new HashMap<String, Date>();
		for (Timeline event : events) {
			if ("collect-article".equals(event.getAction())) {
				if (articleIds.length() != 0) {
					articleIds.append(",");
				}
				articleIds.append(event.getTargetId());
				map.put("article" + event.getTargetId(), event.getCreateAt());
			}

			if ("collect-question".equals(event.getAction())) {
				if (questionIds.length() != 0) {
					questionIds.append(",");
				}
				questionIds.append(event.getTargetId());
				map.put("question" + event.getTargetId(), event.getCreateAt());
			}

		}
		List<HashMap> articles = articleDAO.findByIds(articleIds.toString());
		List<HashMap> questions = questionDAO.findByIds(questionIds.toString());

		List<TimeEvent> result = new ArrayList<TimeEvent>();
		for (HashMap amap : articles) {
			TimeEvent timeEvent = new TimeEvent();
			timeEvent.setEventName("article");
			timeEvent.setMap(amap);
			timeEvent.setEventTime(map.get("article" + amap.get("id")));
			result.add(timeEvent);
		}
		for (HashMap qmap : questions) {
			TimeEvent timeEvent = new TimeEvent();
			timeEvent.setEventName("question");
			timeEvent.setMap(qmap);
			timeEvent.setEventTime(map.get("question" + qmap.get("id")));
			result.add(timeEvent);
		}
		Collections.sort(result, new Comparator() {
		      public int compare(Object o1, Object o2) {
		    	  TimeEvent t1 = (TimeEvent)o1;
		    	  TimeEvent t2 = (TimeEvent)o2;
		    	  return t2.getEventTime().compareTo(t1.getEventTime());
		      }
		   });
		
		pageobj.setList(result);

		return pageobj;
	}


	private String getMaxDate(Date ar, Date qu, Date an) {
		if ((ar.after(qu) || ar.equals(qu)) && (ar.after(an) || ar.equals(an))) {
			return "ar";
		}
		if ((qu.after(ar) || qu.equals(ar)) && (qu.after(an) || qu.equals(an))) {
			return "qu";
		}
		if ((an.after(qu) || an.equals(qu)) && (an.after(ar) || an.equals(ar))) {
			return "an";
		}
		return null;
	}

	@Transactional
	public String addUserAction(String type, String action, int targetId,
			int userId) {
		if (type.equals("article")) {
			if (action.equals("favor")) {
				return articleService.favorArticle(targetId, userId);
			}
			if (action.equals("agree")) {
				return articleService.agreeArticle(targetId, userId);
			}
			if (action.equals("disagree")) {
				return articleService.disagreeArticle(targetId, userId);
			}
			if (action.equals("collect")) {
				String result = articleService.collectArticle(targetId, userId);
				if (result.equals("success")) {
					User user = new User();
					user.setId(userId);
					Timeline t = new Timeline(user, "collect-article",
							targetId, new Date());
					t.setIsPublic(1);
					timelineDAO.addEvent(t);
				}
				return result;

			}
			if (action.equals("cancel-collect")) {
				String result = articleService.cancelCollectArticle(targetId, userId);
				if (result.equals("success")) {
					timelineDAO.deleteEvent(userId,"collect-article",targetId);
				}
				return result;

			}
		} else if (type.equals("question")) {
			if (action.equals("favor")) {
				return questionService.favorQuestion(targetId, userId);
			}
			if (action.equals("agree")) {
				return questionService.agreeQuestion(targetId, userId);
			}
			if (action.equals("disagree")) {
				return questionService.disagreeQuestion(targetId, userId);
			}
			if (action.equals("collect")) {

				String result = questionService.collectQuestion(targetId,
						userId);
				if (result.equals("success")) {
					User user = new User();
					user.setId(userId);
					Timeline t = new Timeline(user, "collect-question",
							targetId, new Date());
					t.setIsPublic(1);
					timelineDAO.addEvent(t);
				}
				return result;
			}
			if (action.equals("cancel-question")) {
				questionActionDAO.cancelCollectQuestion(targetId, userId);
				timelineDAO.deleteEvent(userId,"collect-question",targetId);
				return "success";
			}

		}
		return "error";

	}

	@Transactional
	public Page findMyAttensionForPage(int userId, int page, int pageSize) {
		// TODO Auto-generated method stub
		return relationDAO.findUserAttentionForPage(userId, page, pageSize);
	}

	@Transactional
	public Page findAttensiondMeForPage(int userId, int page, int pageSize) {
		// TODO Auto-generated method stub
		return relationDAO.findAttensiondMeForPage(userId, page, pageSize);
	}

	@Transactional
	public Page findActiveUserByPage(int page, int pageSize) {
		// TODO Auto-generated method stub
		return userDAO.findActiveUserByPage(page, pageSize);
	}

	@Transactional
	public int getUserRelation(int id, int userId) {
		// TODO Auto-generated method stub
		return relationDAO.getUserRelation(id, userId);
	}

	@Transactional
	public List findHotTag(int topN) {
		// TODO Auto-generated method stub
		return tagDAO.getHotTag(topN);
	}
	@Transactional
	public Page findHotUserByPage(int page, int pageSize){
		return userDAO.findHotUserByPage(page, pageSize);
	}
}
